import { Context, Next } from 'koa';
import { AuthService } from '../services/system/authService';
import { createError, HttpError } from './errorHandler';

export class AuthMiddleware {
  private authService: AuthService;

  constructor() {
    this.authService = new AuthService();
  }

  // 验证 JWT token
  authenticate = async (ctx: Context, next: Next): Promise<void> => {
    try {
      const authHeader = ctx.headers.authorization;

      if (!authHeader || !authHeader.startsWith('Bearer ')) {
        throw createError('缺少认证 token', 401);
      }

      const token = authHeader.substring(7); // 移除 'Bearer ' 前缀

      if (!token) {
        throw createError('无效的 token 格式', 401);
      }

      // 验证 token
      const user = await this.authService.verifyToken(token);

      // 将用户信息存储到上下文中
      ctx.state.user = user;

      await next();
    } catch (error: any) {
      if (error.status === 401 || error.status === 403) throw error;
      if (error instanceof HttpError) throw error;
      throw createError('认证失败', 401, error);
    }
  };

  // 可选认证（不强制要求认证）
  optionalAuthenticate = async (ctx: Context, next: Next): Promise<void> => {
    try {
      const authHeader = ctx.headers.authorization;

      if (authHeader && authHeader.startsWith('Bearer ')) {
        const token = authHeader.substring(7);

        if (token) {
          try {
            const user = await this.authService.verifyToken(token);
            ctx.state.user = user;
          } catch (error) {
            // 如果 token 验证失败，继续执行但不设置用户信息
            console.warn('可选认证失败:', error);
          }
        }
      }

      await next();
    } catch (error: any) {
      throw createError('可选认证失败', 401, error);
    }
  };

  // 检查用户角色
  requireRole = (roles: string | string[]) => {
    const requiredRoles = Array.isArray(roles) ? roles : [roles];

    return async (ctx: Context, next: Next): Promise<void> => {
      try {
        const user = ctx.state.user;

        if (!user) {
          throw createError('需要认证', 401);
        }
        const hasIntersection = (arr1: any, arr2: any) => {
          const set2 = new Set(arr2);
          return arr1.some((item: any) => set2.has(item));
        }

        if (!hasIntersection(requiredRoles, user.roles.map((e: any) => e.code))) {
          throw createError('权限不足', 403, '您没有足够的权限');
        }

        await next();
      } catch (error: any) {
        console.log(error, 'roleerror')
        if (error instanceof HttpError) throw error;
        if (error.status === 401 || error.status === 403) throw error;

        throw createError('权限验证失败-requireRole', 403, error);
      }
    };
  };


}

export default AuthMiddleware;